﻿//-----------------------------------------------------------------------
// <copyright file="AuthorizationServiceBase.Roles.cs" company="Alan Rodrigues">
//     Copyright (c) Alan Rodrigues. All rights reserved.
// </copyright>
// <developed>Alan Rodrigues (operninha@gmail.com)</developed>
//-----------------------------------------------------------------------

using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Authorization
{
    using System;
    using Properties;

    public partial class AuthorizationServiceBase
    {
        #region RoleAssignments
        public RoleAssignmentCollection GetAllRoleAssignments(string applicationName, string scopeName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");

            var application = AuthorizationStoreManager.GetApplication(applicationName);
            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.GetAllRoleAssignments", Resources.invalid_application);
            }
            return application.GetRoleAssignments(scopeName);
        }

        /// <summary>
        /// Retorna o nome dos papeis do sistema
        /// </summary>
        /// <param name="applicationName">nome da Application</param>
        /// <param name="scopeName">Name do <seealso cref="Scope"/> onde será feita a busca dos papeis</param>
        /// <returns>Name dos papeis do Sistema</returns>
        public string[] GetAllRoleAssignmentNames(string applicationName, string scopeName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");

            var  app = AuthorizationStoreManager.GetApplication(applicationName);
            
            if (app == null)
            {
                throw new AuthorizationException("AuthorizationService.GetAllRoleAssignmentNames", Resources.invalid_application);
            }

            return app.GetRoleAssignmentNames(scopeName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="applicationName"></param>
        /// <param name="scopeName"></param>
        /// <param name="roleName"></param>
        /// <returns></returns>
        public bool RoleAssignmentExists(string applicationName, string scopeName, string roleName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleName, true, true, false, 64, "roleName");
            var app = AuthorizationStoreManager.GetApplication(applicationName);

            if (app == null)
            {
                throw new AuthorizationException("AuthorizationService.RoleAssignmentExists", Resources.invalid_application);
            }

            return app.RoleAssignmentExists(roleName, scopeName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="applicationName"></param>
        /// <param name="scopeName"></param>
        /// <param name="roleAssignmentName"></param>
        /// <returns></returns>
        public RoleAssignment GetRoleAssignment(string applicationName, string scopeName, string roleAssignmentName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleAssignmentName, true, true, false, 64, "roleAssignmentName");

            var app = AuthorizationStoreManager.GetApplication(applicationName);

            if (app == null)
            {
                throw new AuthorizationException("AuthorizationService.GetRoleAssignment", Resources.invalid_application);
            }

            return app.GetRoleAssignment(roleAssignmentName, scopeName);
        }

        public RoleAssignment CreateRoleAssignment(string applicationName, string scopeName, string roleDefinitionName, string roleAssignmentName, string description)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleAssignmentName, true, true, false, 64, "roleAssignmentName");
            SecUtility.CheckParameter(ref roleDefinitionName, true, true, false, 64, "roleDefinitionName");

            Application application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.CreateRoleAssignment", Resources.invalid_application);
            }
             
            var role = application.CreateRoleAssignment(roleAssignmentName, description, scopeName);
            role.AddRoleDefinition(roleDefinitionName);
            role.Save();
            return role;
        }

        public void DeleteRoleAssignment(string applicationName, string scopeName, string roleName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleName, true, true, false, 64, "roleName");

           var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.DeleteRoleAssignment", Resources.invalid_application);
            }

            application.DeleteRoleAssignment(roleName, scopeName);
            application.Save();
        }

        public void UpdateRoleAssignment(string applicationName, string scopeName, string roleName, string newRoleName, string newDescription)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleName, true, true, false, 64, "roleName");
            SecUtility.CheckParameter(ref newRoleName, true, true, false, 64, "newRoleName");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.UpdateRoleAssignment", Resources.invalid_application);
            }

            var role =  application.UpdateRoleAssignment(roleName, scopeName, newRoleName, newDescription);
            role.Save();
        }


        public void AddUsersToRoleAssignments(string applicationName, string scopeName, string[] SIDs, string[] roleNames)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckArrayParameter(ref roleNames, true, true, false, 64, "roleNames");
            SecUtility.CheckArrayParameter(ref SIDs, true, true, false, 64, "SIDs");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.AddUsersToRoleAssignments", Resources.invalid_application);
            }

            foreach (var roleName in roleNames)
            {
                var role = application.GetRoleAssignment(roleName, scopeName);
         
                role.AddMembers(SIDs);
                role.Save();
            }
        }

        public void AddUserNamesToRoleAssignments(string applicationName, string scopeName, string[] usernames, string[] roleNames)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckArrayParameter(ref roleNames, true, true, false, 64, "roleNames");
            SecUtility.CheckArrayParameter(ref usernames, true, true, false, 64, "usernames");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.AddUserNamesToRoleAssignments", Resources.invalid_application);
            }

            foreach (var roleName in roleNames)
            {
                var role = application.GetRoleAssignment(roleName, scopeName);
                if (role == null)
                    throw new AuthorizationException("AuthorizationService.AddUserNamesToRoleAssignments", string.Format(Resources.roleassignment_not_found, roleName));
                
                role.AddMemberNames(usernames);                
                role.Save();
            }
        }

        public string[] FindUsersInRoleAssignment(string usernameToMatch, string applicationName, string scopeName, string roleAssignmentName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref usernameToMatch, true, true, false, 64, "usernameToMatch");
            SecUtility.CheckParameter(ref roleAssignmentName, true, true, false, 64, "roleAssignmentName");
            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.FindUsersInRoleAssignment", Resources.invalid_application);
            }

            var role = application.GetRoleAssignment(roleAssignmentName, scopeName);
            var users =  role != null ? role.GetMembersName() : null;
          
            if (users == null)
                return null;

            var usersResult = new List<string>();
            
            var reg = new Regex(usernameToMatch);
            foreach (var user in users)
            {
                if (reg.IsMatch(user))
                     usersResult.Add(user);
                else if (IsUserInRoleAssignment(user, applicationName, scopeName, roleAssignmentName))
                      usersResult.Add(user);
            }

            return usersResult.ToArray();
        }

        public string[] GetUsersInRoleAssignment(string applicationName, string scopeName, string roleAssignmentName)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckParameter(ref roleAssignmentName, true, true, false, 64, "roleAssignmentName");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.GetUsersInRoleAssignment", Resources.invalid_application);
            }

           
           var role =  application.GetRoleAssignment(roleAssignmentName, scopeName);
          
           return role != null ? role.GetMembersName() : null;
        }

        public void RemoveUsersFromRoleAssignments(string applicationName, string scopeName, string[] Sids, string[] roleAssignmentNames)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckArrayParameter(ref Sids, true, true, false, 64, "Sids");
            SecUtility.CheckArrayParameter(ref roleAssignmentNames, true, true, false, 64, "roleAssignmentNames");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.RemoveUsersFromRoleAssignments", Resources.invalid_application);
            }
            foreach (var roleAssignmentName in roleAssignmentNames)
            {
                var role = application.GetRoleAssignment(roleAssignmentName, scopeName);
                if (role != null)
                {
                    role.DeleteMembers(Sids);
                    role.Save();
                }
            }
        }

        public void RemoveUserNameFromRoleAssignments(string applicationName, string scopeName, string[] usernames, string[] roleAssignmentNames)
        {
            SecUtility.CheckParameter(ref applicationName, true, true, false, 64, "applicationName");
            SecUtility.CheckArrayParameter(ref usernames, true, true, false, 64, "usernames");
            SecUtility.CheckArrayParameter(ref roleAssignmentNames, true, true, false, 64, "roleAssignmentNames");

            var application = AuthorizationStoreManager.GetApplication(applicationName);

            if (application == null)
            {
                throw new AuthorizationException("AuthorizationService.RemoveUsersFromRoleAssignments", Resources.invalid_application);
            }
            foreach (var roleAssignmentName in roleAssignmentNames)
            {
                var role = application.GetRoleAssignment(roleAssignmentName, scopeName);
                if ( role != null)
                {
                    role.DeleteMemberNames(usernames);
                    role.Save();
                }
            }
        }
        
        #endregion
    }
}
